package com.zhu.concurrent;

import org.junit.Test;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: zhujiabao
 * @Date: 2022/04/28/14:52
 * @Description:创建线程的5种方式
 */
public class CreateThread {

    /**
     * 1.继承 Thread 类
     * 如代码所示：继承 Thread 类，并重写了其中的 run () 方法，之后直接调用 start () 即可实现多线程。
     * 相信上面这种方式你一定非常熟悉，并且经常在工作中使用它们。
     */
    @Test
    public void threadTest(){
        new MyThread().start();
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("通过集成 Thread 类实现线程");
        }
    }


    /**
     * 2.实现 Rannable 接口创建线程；
     * 如代码所示，这种方法其实是定义一个线程执行的任务（run 方法里面的逻辑）并没有创建线程。
     * 它首先通过 MyRunnable 类实现 Runnable 接口，然后重写 run () 方法，之后还要把这个实现了 run () 方法的实例传到 Thread 类中才可以实现多线程。
     */
    @Test
    public void runnableTest(){
        //使用
        //1.创建 MyRunnable实例
        MyRunnable myRunnable = new MyRunnable();
        //2.创建 Thread 对象
        //3.将 MyRunnable 放入 Thread 实例中
        Thread thread = new Thread(myRunnable);
        //4.通过线程对象操作线程（运行、停止）
        thread.start();

        //lambda写法
        new Thread(()-> System.out.println("通过实现 Runnable 方式实现线程22222")).start();

    }

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("通过实现 Runnable 方式实现线程");
        }
    }


    /**
     * 3.通过线程池创建线程
     * 本质也是 new Thread（）
     */
    @Test
    public void threadPoolTest(){

        // 10是核心线程数
        ExecutorService service = Executors.newFixedThreadPool(10);
        service.execute(new MyRunnable());

    }

    /**
     * 4.通过实现 Callable 接口创建线程
     * 它们可以提交到线程池执行，通过 sumbit 方法提交。这时就参考方式三，由线程工厂负责创建线程。
     * 当然，还有其他方法执行 Callable 任务。但是不管怎么说，它还是离不开实现 Runnable 接口和继承 Thread 类这两种方式。
     */
    @Test
    public void callableTest(){
        //使用方法
        //1.创建线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        //2.提交任务，并用 Future 提交返回结果
        Future<Integer> future = service.submit(new MyCallable());
        Integer integer = 0;
        try {
            //future.isDone() 判断线程任务是否已经执行完了
            System.out.println(future.isDone());
            //future.get() 获取线程的返回值
            integer = future.get();
            System.out.println(future.isDone());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(integer);
    }

    class MyCallable implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            Thread.sleep(1000);
            return new Random().nextInt();
        }

    }


    /**
     * 5.Timer 创建线程
     * 注：内部类中不能含有静态成员变量和静态方法。
     *
     * 深入到源码后，注意到 TimerThread ，它还是继承于 Thread ，
     * 所以 Timer 创建线程最后又绕回到最开始说的两种方式了。
     */

    public static void main(String[] args) {
        timer();
    }
    /**
     * 指定时间 time 执行 schedule(TimeeTask task,Date time)
     */
    public static void timer(){
        Timer timer = new Timer();
        // 设定指定的时间time,此处为2000毫秒后执行
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行定时任务");
            }
        },2000);

    }





}
